#include <lcir/ADT/Range.h>
#include <lcir/IR/Argument.h>
#include <lcir/IR/Expression.h>
#include <lcir/IR/LambdaBase.h>
#include <lcir/IR/LambdaProto.h>
#include <lcir/IR/LambdaType.h>
#include <lcir/IR/Prototype.h>
#include <lcir/IR/Value.h>

#include <stdexcept>
#include <vector>
namespace lcir {

std::vector<Value *> LambdaBase::getArgs() const {
  std::vector<Value *> ret;
  for (auto &arg : arguments) {
    ret.push_back(&arg);
  }
  return ret;
}

Expression *LambdaBase::insertExpr(Expression *insertPoint,
                                   std::unique_ptr<Expression> expr) {
  expr->setParent(this);
  auto *ptr = expr.release();
  exprs.insert(insertPoint, ptr);
  ptr->getOp()->insertCallBack(ptr);
  return ptr;
}
Expression *LambdaBase::insertExprAfter(Expression *insertPoint,
                                        std::unique_ptr<Expression> expr) {
  expr->setParent(this);
  auto *ptr = expr.release();
  exprs.insertAfter(insertPoint, ptr);
  ptr->getOp()->insertCallBack(ptr);
  return ptr;
}
Expression *LambdaBase::pushBackExpr(std::unique_ptr<Expression> expr) {
  expr->setParent(this);
  auto *ptr = expr.release();
  exprs.pushBack(ptr);
  ptr->getOp()->insertCallBack(ptr);
  return ptr;
}
Expression *LambdaBase::pushFrontExpr(std::unique_ptr<Expression> expr) {
  expr->setParent(this);
  auto *ptr = expr.release();
  exprs.pushFront(ptr);
  ptr->getOp()->insertCallBack(ptr);
  return ptr;
}
template <class RangeType>
static void
walkBase(RangeType &range,
         const std::function<void(const Expression *expr)> &callback,
         bool isBackWard) {
  for (auto &expr : range) {
    callback(&expr);
    for (auto *opd : expr.getOperands()) {
      if (auto *lambda = opd->getValue()->template dyn_cast<LambdaBase>())
        lambda->walk(callback, isBackWard);
    }
  }
}
LambdaBase::exprList::iterator LambdaBase::end() { return exprs.end(); }
LambdaBase::exprList::iterator LambdaBase::begin() { return exprs.begin(); }
LambdaBase::exprList::constIterator LambdaBase::end() const {
  return exprs.end();
}
LambdaBase::exprList::constIterator LambdaBase::begin() const {
  return exprs.begin();
}

} // namespace lcir